package polimi.disttest;

import java.util.*;

import polimi.reds.Filter;
import polimi.reds.Message;

/**
 * This class represents a generic filter
 *  
 * @author daniel
 *
 */
public class GenericFilter implements Filter {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -7209836800187167690L;
	private List<GenericMessage> prototypeMessages;
	
	/**
	 * Creates an empty filter
	 */
	public GenericFilter() {
		prototypeMessages = new ArrayList<GenericMessage>();
	}
	
	/**
	 * Creates a filter that filters that type of messages
	 * 
	 * @param message The message to be filtered
	 */
	public GenericFilter(GenericMessage message) {
		prototypeMessages = new ArrayList<GenericMessage>();
		prototypeMessages.add(message);
	}
	
	/**
	 * Creates a filter that filters many type of messages
	 * 
	 * @param prototypeMessages The messages to be filtered
	 */
	public GenericFilter(List<GenericMessage> prototypeMessages) {
		this.prototypeMessages = new ArrayList<GenericMessage>();
		this.prototypeMessages.addAll(prototypeMessages);
		//Collections.sort(this.prototypeMessages, new LexicalComparator<Message>());
	}
	
	/**
	 * Aggregates this filter with another filter
	 * 
	 * @param filter Other filter to aggregate
	 * @return The composed filter
	 */
	public GenericFilter union(GenericFilter filter) {
		
		List<GenericMessage> newMessageSet = new ArrayList<GenericMessage>(filter.getPrototypeMessages());
		
		for (GenericMessage m:prototypeMessages) {
			if (!newMessageSet.contains(m)) {
				newMessageSet.add(m);
			}
		}
		
		//Arrays.sort(prototypeMessages.toArray());
		
		return new GenericFilter(newMessageSet);
	}
	
	/**
	 * Checks if the messages matches this filter
	 * @param message
	 * @return
	 */
	public boolean matches(Message message) {
		if (prototypeMessages.contains(message)) {
			return true;
		} else {
			return false;
		}
	}
	
	public boolean equals(Object obj) {
		if (!(obj instanceof GenericFilter)) {
			return super.equals(obj);
		}
		
		GenericFilter otherFilter = (GenericFilter) obj;
		
		if (otherFilter.size() != size()) {
			return false;
		}
		
		List<GenericMessage> otherPrototypeMessages = otherFilter.getPrototypeMessages();
		
		for (GenericMessage m:prototypeMessages) {
			if (!otherPrototypeMessages.contains(m)) {
				return false;
			}
		}
		
		return true;
	}
	
	/**
	 * Get the list of prototype messages
	 * 
	 * @return List of prototype messages
	 */
	public List<GenericMessage> getPrototypeMessages() {
		return prototypeMessages;
	}
	
	/**
	 * Get the list of prototype messages id
	 * 
	 * @return List of prototype messages id
	 */
	public List<Integer> getPrototypeMessagesID() {
		List<Integer> prototypeMessagesID = new ArrayList<Integer>();
		
		for (GenericMessage m:prototypeMessages) {
			prototypeMessagesID.add(m.getMessageClass());
		}
		
		return prototypeMessagesID;
	}
	
	/**
	 * Convert the filter to a string
	 */
	public String toString() {
		
		if (prototypeMessages.size() == 0) {
			return "EMPTY";
		} else if (prototypeMessages.size() == 1) {
			return "{"+prototypeMessages.get(0) + "}";
		}
		
		String s = "{";
		int i=0;
		for (GenericMessage m:prototypeMessages) {
			s += m;
			i++;
			if (i<prototypeMessages.size()) {
				s += ",";
			}
		}
		s += "}";
		
		return s;
	}
	
	/**
	 * Get the size of the filter
	 * 
	 * @return the size of the filter
	 */
	public int size() {
		return prototypeMessages.size();
	}

}
